# -*- coding: utf-8 -*-
"""
UTc! module: src.sandbox.generic_rendering

Purpose
=======
 Provides facilities for visually rendering generic objects for development
 purposes.
 
 Note:: This contains feature-overlap with src.rendering.rendering, but this
 module is frozen and used only by ode_rendering, which is also frozen, so
 no conflict should emerge. DO NOT IMPORT THIS MODULE IN NEW CODE; USE
 C{src.rendering.rendering} INSTEAD.
 
Legal
=====
 All code, unless otherwise indicated, is original, and subject to the
 terms of the GPLv2, which is provided in COPYING.
 
 (C) Neil Tallim, 2009
"""
import OpenGL.GL as GL
import OpenGL.GLU as GLU

import src.matrix as matrix

_CUBE_ID = None #: The OpenGL List ID of a unit cube, used to render boxes.
_RENDER_SOLID = False #: True if solid rendering is to be used; False if wireframe rendering is desired.

def init(render_solid):
	"""
	Initialises this module, defining the unit cube and locking the rendering
	style.
	
	@type render_solid: bool
	@param render_solid: True if solid polygons should be drawn; False if
	    wireframe rendering is preferred.
	"""
	global _RENDER_SOLID
	_RENDER_SOLID = render_solid
	
	global _CUBE_ID
	_CUBE_ID = GL.glGenLists(1)
	GL.glNewList(_CUBE_ID, GL.GL_COMPILE)
	GL.glFrontFace(GL.GL_CCW)
	
	GL.glBegin(GL.GL_QUADS)
	GL.glNormal(0, 1, 0)
	GL.glVertex3f(0.5, 0.5, -0.5)
	GL.glVertex3f(-0.5, 0.5, -0.5)
	GL.glVertex3f(-0.5, 0.5, 0.5)
	GL.glVertex3f(0.5, 0.5, 0.5)
	
	GL.glNormal(0, -1, 0)
	GL.glVertex3f(0.5, -0.5, 0.5)
	GL.glVertex3f(-0.5, -0.5, 0.5)
	GL.glVertex3f(-0.5, -0.5, -0.5)
	GL.glVertex3f(0.5, -0.5, -0.5)
	
	GL.glNormal(0, 0, 1)
	GL.glVertex3f(0.5, 0.5, 0.5)
	GL.glVertex3f(-0.5, 0.5, 0.5)
	GL.glVertex3f(-0.5, -0.5, 0.5)
	GL.glVertex3f(0.5, -0.5, 0.5)
	
	GL.glNormal(0, 0, -1)
	GL.glVertex3f(0.5, -0.5, -0.5)
	GL.glVertex3f(-0.5, -0.5, -0.5)
	GL.glVertex3f(-0.5, 0.5, -0.5)
	GL.glVertex3f(0.5, 0.5, -0.5)
	
	GL.glNormal(-1, 0, 0)
	GL.glVertex3f(-0.5, 0.5, 0.5)
	GL.glVertex3f(-0.5, 0.5, -0.5)
	GL.glVertex3f(-0.5, -0.5, -0.5)
	GL.glVertex3f(-0.5, -0.5, 0.5)
	
	GL.glNormal(1, 0, 0)
	GL.glVertex3f(0.5, 0.5, -0.5)
	GL.glVertex3f(0.5, 0.5, 0.5)
	GL.glVertex3f(0.5, -0.5, 0.5)
	GL.glVertex3f(0.5, -0.5, -0.5)
	GL.glEnd()
	GL.glEndList()
	
def initMatrixQuat(position, rotation_matrix):
	"""
	Initialises the GL rendering matrix based on a rotation matrix.
	
	Rotations are expected to be provided in the order of roll, yaw, and pitch.
	
	@type position: sequence(3)
	@param position: The (x, y, z) position at which the object will appear.
	@type rotation_matrix: sequence(9)
	@param rotation_matrix: The rotation matrix to apply to the object.
	"""
	GL.glMultMatrixf(matrix.buildRenderMatrix(rotation_matrix, position))
	
def initMatrixEuler(position, rotation):
	"""
	Initialises the GL rendering matrix based on Euler rotations.
	
	Rotations are applied in the order of roll, yaw, and pitch.
	
	@type position: sequence(3)
	@param position: The (x, y, z) position at which the object will appear.
	@type rotation: sequence(3)
	@param rotation: The (x, y, z) rotations to apply to the object.
	"""
	(x, y, z) = position
	(rx, ry, rz) = rotation
	GL.glTranslate(x, y, z)
	GL.glRotate(rz, 0, 0, 1)
	GL.glRotate(ry, 0, 1, 0)
	GL.glRotate(rx, 1, 0, 0)
	
def renderBox(lengths, r, g, b):
	"""
	Renders a box with the specified dimensions and colour based on a previously
	set rendering matrix.
	
	@type lengths: sequence(3)
	@param lengths: The (x, y, z) lengths of the box to be rendered.
	@type r: float
	@param r: The red-value to use when rendering.
	@type g: float
	@param g: The green-value to use when rendering.
	@type b: float
	@param b: The blue-value to use when rendering.
	"""
	_setRenderProperties(r, g, b)
	GL.glScale(*lengths)
	GL.glCallList(_CUBE_ID)
	
def renderSphere(radius, r, g, b):
	"""
	Renders a sphere of the specified size and colour based on a previously set
	rendering matrix.
	
	@type radius: float
	@param radius: The radius of the sphere to be rendered.
	@type r: float
	@param r: The red-value to use when rendering.
	@type g: float
	@param g: The green-value to use when rendering.
	@type b: float
	@param b: The blue-value to use when rendering.
	"""
	_setRenderProperties(r, g, b)
	quadric = GLU.gluNewQuadric()
	fragments = radius * 2
	GLU.gluSphere(quadric, radius, 10, 10)
	GLU.gluDeleteQuadric(quadric)
	
def _setRenderProperties(r, g, b):
	"""
	Sets the OpenGL parameters needed to ensure that ODE elements are rendered
	properly.
	
	@type r: float
	@param r: The red-value to use when rendering.
	@type g: float
	@param g: The green-value to use when rendering.
	@type b: float
	@param b: The blue-value to use when rendering.
	"""
	if _RENDER_SOLID:
		GL.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_FILL)
	else:
		GL.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_LINE)
	GL.glColor(r, g, b)
	